Topic: 開放資料 - 水庫CTSI卡爾森指數-資料視覺化¶

File: 18_water_ctsi_visualization.ipynb

Author: Ming-Chang Lee

Date: 2025.06.16

Data source: https://data.gov.tw/dataset/6345

References:

https://github.com/rwepa/python_data_scientist

參考 RWEPA | Python AQI 空氣品質指標資料分析:

https://rwepa.blogspot.com/2025/03/python-aqi-application.html

🌸YouTube (包括中文字幕):https://youtu.be/0UJbhVWDuI4

Jupyter notebook下載: https://github.com/rwepa/python_data_scientist/blob/main/tutorial_air_quality_index/tutorial_air_quality_index.ipynb

大綱¶

1.商業理解

2.資料理解

2.1 模組與資料匯入

2.2 資料摘要

2.3 探索性資料分析(Exploratory Data Analysis, EDA)

2.4 資料視覺化

3.資料準備

4.建立模型

5.模型評估與測試

6.佈署應用與結論

參考文獻

1.商業理解¶

  • 研究目的: 探討水庫CTSI卡爾森指數資料並進行資料視覺化分析.

  • 資料來源: 政府資料開放平台-水庫水質監測資料

  • 檔案下載: https://data.gov.tw/dataset/6345

  • 檔案名稱: wqx_p_03.csv

  • 資料筆數: 1000

  • 欄位數量為19個:

欄位名稱 中文說明
測站代碼 siteid
測站名稱 sitename
測站英文名稱 siteengname
水庫名稱 damname
縣市 county
鄉鎮市區 township
twd97經度 twd97lon
twd97緯度 twd97lat
twd97二度分帶x twd97tm2x
twd97二度分帶y twd97tm2y
採樣日期 sampledate
採樣水層 samplelayer
採樣深度 sampledepth
測項名稱 itemname
測項英文名稱 itemengname
測項英文簡稱 itemengabbreviation
監測值 itemvalue
測項單位 itemunit
備註 note
  • 欄位包括地理變數等六大類別:

    1. 背景變數4個: 測站代碼、測站名稱、測站英文名稱、水庫名稱
    2. 地理變數6個: 縣市、鄉鎮市區、twd97經度、twd97緯度、twd97二度分帶x、twd97二度分帶y
    3. 採樣變數2個: 採樣水層、採樣深度
    4. 水質變數5個: 測項名稱、測項英文名稱、測項英文簡稱、監測值、測項單位
    5. 日期時間變數1個: 採樣日期
    6. 其他變數1個: 備註
  • 優養化(Eutrophication):

    • 水體中氮、磷等植物營養物質含量過高引起藻類迅速繁殖,產生藻華現象的過程。
    • 其間由於釋放藻毒素以及增加水中有機質含量,致使水體溶氧量下降,造成水資源利用時的困擾與水體生態平衡的破壞。
    • ㄧ般水體依優養化程度可概分為三大類(1).貧養性 (2)普養性 (3).優養性。
    • 參考資料: https://wq.moenv.gov.tw/EWQP/zh/Encyclopedia/NounDefinition/Pedia_01.aspx
  • 卡爾森指數(Carlson Trophic State Index, CTSI or Carlson's TSI):

    • 一般可以使用卡爾森指數(Carlson, 1977)做為衡量水體優養化現象基準。

    • 考慮 $TP$ = 總磷濃度(μg/L)、$Chl-a$ = 葉綠素a濃度(μg/L)、$SD$ = 透明度(m),則 $CTSI = \frac{TSI(TP) + TSI(Chl-a) + TSI(SD)}{3}$,其中

      • $TSI (TP) = 14.42 \times ln{TP} + 4.15$
      • $TSI (Chl-a) = 9.81 \times ln{Chl-a} + 30.6$
      • $TSI (SD) = 60 - 14.41 \times ln{SD}$
    • 卡爾森指數優養程度表:

卡爾森指數 優養程度
CTSI < 40 貧養
40 ≦ CTSI ≦ 50 普養
CTSI > 50 優養

2.資料理解¶

資料理解包括以下主題, 其中模組與資料匯入及資料摘要為必需主題:

  • 模組與資料匯入【必要項目】
  • 資料摘要【必要項目】
  • 探索性資料分析
  • 資料視覺化
  • 資料清理
  • 資料合併
  • 特徵選擇
  • 資料轉換

本研究使用 Python 程式語言(Python, 2024)並參考RWEPA網站(Lee, 2024)與Ashouri 等人(2023).

  • 安裝 folium 模組: pip install folium

image

2.1 模組與資料匯入¶

In [8]:
# 模組匯入
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import pyplot
import seaborn as sns
from pandas.plotting import scatter_matrix
import plotly.express as px
import plotly.graph_objects as go

# 匯入地圖模組, 記得先安裝 pip install folium
import folium

# 設定中文字型
import matplotlib
matplotlib.rcParams['font.sans-serif'] = ['Microsoft YaHei'] # For Windows
# matplotlib.rcParams['font.sans-serif'] = ['Noto Serif CJK JP'] # For Ubuntu
matplotlib.rcParams['axes.unicode_minus'] = False
In [9]:
# 匯入資料集
urls = 'wqx_p_03.csv'
df = pd.read_csv(urls)

# 顯示資料
df

# 測站名稱有29個
# 每筆記錄有25筆資料列(葉綠素a ~ 卡爾森指數)
# 每筆記錄包括一個以上 sampledepth = {0.5, 3.2, 7.6, ...}
# 湖山水庫二的第1筆資料為第 0列 ~ 第24列, sampledate = 2025/2/4  09:45:00 AM
# 湖山水庫二的第2筆資料為第25列 ~ 第24列, sampledate = 2025/2/4  09:45:00 AM
Out[9]:
siteid sitename siteengname damname county township twd97lon twd97lat twd97tm2x twd97tm2y sampledate samplelayer sampledepth itemname itemengname itemengabbreviation itemvalue itemunit note
0 2212 湖山水庫二 NaN 湖山水庫 雲林縣 NaN 120.630278 23.679167 212291.03 2619541.36 2025-02-04 09:45:00 底水 7.6 葉綠素a Chlorophyl-A Chl_a 3.2 μg/L NaN
1 2212 湖山水庫二 NaN 湖山水庫 雲林縣 NaN 120.630278 23.679167 212291.03 2619541.36 2025-02-04 09:45:00 底水 7.6 總磷 Total-Phosphate TP 0.020 mg/L NaN
2 2212 湖山水庫二 NaN 湖山水庫 雲林縣 NaN 120.630278 23.679167 212291.03 2619541.36 2025-02-04 09:45:00 底水 7.6 正磷酸鹽 PO4-P PO4 - mg/L NaN
3 2212 湖山水庫二 NaN 湖山水庫 雲林縣 NaN 120.630278 23.679167 212291.03 2619541.36 2025-02-04 09:45:00 底水 7.6 溶氧飽和度 Dissolved Oxygen Saturation DOS 92.8 % NaN
4 2212 湖山水庫二 NaN 湖山水庫 雲林縣 NaN 120.630278 23.679167 212291.03 2619541.36 2025-02-04 09:45:00 底水 7.6 溶氧(滴定法) Dissolved Oxygen DO2 - mg/L NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
995 2177 鏡面水庫二 Ching-Mien Reservoir II 鏡面水庫 臺南市 NaN 120.488463 23.058074 197583.15 2550805.52 2025-02-10 14:14:54 表水 0.5 濁度 Turbidity TB 6.6 NTU NaN
996 2177 鏡面水庫二 Ching-Mien Reservoir II 鏡面水庫 臺南市 NaN 120.488463 23.058074 197583.15 2550805.52 2025-02-10 14:14:54 表水 0.5 酸鹼值 pH pH 7.92 NaN
997 2177 鏡面水庫二 Ching-Mien Reservoir II 鏡面水庫 臺南市 NaN 120.488463 23.058074 197583.15 2550805.52 2025-02-10 14:14:54 表水 0.5 透明度 Transparency SD 0.5 m NaN
998 2177 鏡面水庫二 Ching-Mien Reservoir II 鏡面水庫 臺南市 NaN 120.488463 23.058074 197583.15 2550805.52 2025-02-10 14:14:54 表水 0.5 水溫 Water Temperature WT 21.5 ℃ NaN
999 2177 鏡面水庫二 Ching-Mien Reservoir II 鏡面水庫 臺南市 NaN 120.488463 23.058074 197583.15 2550805.52 2025-02-10 14:14:54 表水 0.5 卡爾森指數 Carlson Trophic State Index CTSI 59 NaN NaN

1000 rows × 19 columns

注意: 資料分析的心法中提及三大技巧: 1.群組 2.時間 3建立評變數。

2.2 資料摘要¶

In [12]:
# 資料維度
df.shape # (1000, 19)
Out[12]:
(1000, 19)
In [13]:
# 欄位名稱
df.columns
Out[13]:
Index(['siteid', 'sitename', 'siteengname', 'damname', 'county', 'township',
       'twd97lon', 'twd97lat', 'twd97tm2x', 'twd97tm2y', 'sampledate',
       'samplelayer', 'sampledepth', 'itemname', 'itemengname',
       'itemengabbreviation', 'itemvalue', 'itemunit', 'note'],
      dtype='object')
In [14]:
# 資料型態
# 變數包括 int64(整數)、float64(實數)、object(字串)
# itemvalue 為 object(字串)
df.dtypes
Out[14]:
siteid                   int64
sitename                object
siteengname             object
damname                 object
county                  object
township               float64
twd97lon               float64
twd97lat               float64
twd97tm2x              float64
twd97tm2y              float64
sampledate              object
samplelayer             object
sampledepth            float64
itemname                object
itemengname             object
itemengabbreviation     object
itemvalue               object
itemunit                object
note                   float64
dtype: object
In [15]:
# 採樣日期(sampledate) 匯入資料為 object (字串), 轉換為日期時間.
df['sampledate'] = pd.to_datetime(df['sampledate'])
df['sampledate']
Out[15]:
0     2025-02-04 09:45:00
1     2025-02-04 09:45:00
2     2025-02-04 09:45:00
3     2025-02-04 09:45:00
4     2025-02-04 09:45:00
              ...        
995   2025-02-10 14:14:54
996   2025-02-10 14:14:54
997   2025-02-10 14:14:54
998   2025-02-10 14:14:54
999   2025-02-10 14:14:54
Name: sampledate, Length: 1000, dtype: datetime64[ns]
In [16]:
# 資料摘要
df_describe = df.describe(include='all')
df_describe
Out[16]:
siteid sitename siteengname damname county township twd97lon twd97lat twd97tm2x twd97tm2y sampledate samplelayer sampledepth itemname itemengname itemengabbreviation itemvalue itemunit note
count 1000.000000 1000 875 1000 1000 0.0 1000.000000 1000.000000 1000.000000 1.000000e+03 1000 1000 975.000000 1000 1000 1000 1000 960 0.0
unique NaN 29 27 18 9 NaN NaN NaN NaN NaN NaN 3 NaN 25 24 25 393 8 NaN
top NaN 湖山水庫一 Feng-Shan Reservoir IV 鳳山水庫 高雄市 NaN NaN NaN NaN NaN NaN 表水 NaN 葉綠素a Dissolved Oxygen Chl_a - mg/L NaN
freq NaN 75 75 150 275 NaN NaN NaN NaN NaN NaN 725 NaN 40 80 40 377 600 NaN
mean 2192.325000 NaN NaN NaN NaN NaN 120.346520 23.164780 223954.940923 2.562615e+06 2025-02-11 15:09:39.975000064 NaN 5.030769 NaN NaN NaN NaN NaN NaN
min 2177.000000 NaN NaN NaN NaN NaN 118.381116 22.133792 182975.640000 2.448387e+06 2025-02-04 09:45:00 NaN 0.500000 NaN NaN NaN NaN NaN NaN
25% 2183.750000 NaN NaN NaN NaN NaN 120.351979 22.538902 187263.195000 2.493354e+06 2025-02-04 11:14:46 NaN 0.500000 NaN NaN NaN NaN NaN NaN
50% 2190.000000 NaN NaN NaN NaN NaN 120.514905 23.097123 211810.820000 2.555110e+06 2025-02-10 11:39:59 NaN 0.500000 NaN NaN NaN NaN NaN NaN
75% 2201.250000 NaN NaN NaN NaN NaN 120.668030 23.679167 232767.750000 2.619541e+06 2025-02-13 11:52:39 NaN 7.600000 NaN NaN NaN NaN NaN NaN
max 2212.000000 NaN NaN NaN NaN NaN 121.302083 24.806722 313893.660000 2.744404e+06 2025-02-26 10:32:06 NaN 33.800000 NaN NaN NaN NaN NaN NaN
std 10.688012 NaN NaN NaN NaN NaN 0.626843 0.773537 41767.667180 8.565253e+04 NaN NaN 8.884444 NaN NaN NaN NaN NaN NaN
In [17]:
# 篩選經緯度資料
df_location = df[['sitename', 'twd97lon', 'twd97lat']]
df_location = df_location.drop_duplicates()
df_location.shape
Out[17]:
(29, 3)
In [18]:
df_location
Out[18]:
sitename twd97lon twd97lat
0 湖山水庫二 120.630278 23.679167
50 湖山水庫一 120.625556 23.684083
125 蘭湖水庫 118.381116 24.451954
150 金湖水庫 118.458370 24.434472
175 寶二水庫一 121.044444 24.719495
200 石門水庫六 121.302083 24.806722
225 大埔水庫 120.983752 24.675913
250 德基水庫五 121.247684 24.270084
275 七美水庫 119.434562 23.211729
300 小池水庫 119.509307 23.610886
325 西安水庫 119.497236 23.364550
350 東衛水庫 119.597683 23.567763
375 興仁水庫 119.606836 23.549442
400 成功水庫 119.625964 23.577479
425 牡丹水庫三 120.782318 22.147105
475 牡丹水庫二 120.782567 22.140403
525 牡丹水庫一 120.781288 22.133792
575 鳳山水庫四 120.389622 22.535145
650 鳳山水庫三 120.388483 22.538672
675 鳳山水庫二 120.390094 22.538978
700 鳳山水庫一 120.392360 22.540565
725 澄清湖水庫四 120.350500 22.663972
750 澄清湖水庫三 120.347806 22.661806
775 澄清湖水庫二 120.352472 22.660361
825 澄清湖水庫一 120.354556 22.654472
850 南化水庫三 120.564178 23.126354
875 南化水庫二 120.554626 23.106803
925 南化水庫一 120.541347 23.087443
975 鏡面水庫二 120.488463 23.058074
In [19]:
# 資料篩選: sampledepth = 0.5
df_ctsi = df.loc[df['sampledepth'] == 0.5, ['sitename', 'itemname', 'itemvalue']]
df_ctsi # 700*3
Out[19]:
sitename itemname itemvalue
25 湖山水庫二 葉綠素a 3.3
26 湖山水庫二 總磷 0.019
27 湖山水庫二 正磷酸鹽 -
28 湖山水庫二 溶氧飽和度 89.4
29 湖山水庫二 溶氧(滴定法) -
... ... ... ...
995 鏡面水庫二 濁度 6.6
996 鏡面水庫二 酸鹼值 7.92
997 鏡面水庫二 透明度 0.5
998 鏡面水庫二 水溫 21.5
999 鏡面水庫二 卡爾森指數 59

700 rows × 3 columns

In [20]:
# 篩選資料, 考慮 temname = {葉綠素a, 總磷, 透明度, 卡爾森指數}

# 方法1
# df.loc[(df['欄位1'] > 30) & (df['欄位2'] == 'A'), ['欄位1', '欄位2', '欄位3']]
# df.loc[(df['欄位1'] > 30) | (df['欄位2'] == 'A'), ['欄位1', '欄位2', '欄位3']]

mydf = df_ctsi.loc[(df_ctsi['itemname'] == '葉綠素a') | (df_ctsi['itemname'] == '總磷') | (df_ctsi['itemname'] == '透明度') | (df_ctsi['itemname'] == '卡爾森指數'),]
mydf # 112*3
Out[20]:
sitename itemname itemvalue
25 湖山水庫二 葉綠素a 3.3
26 湖山水庫二 總磷 0.019
47 湖山水庫二 透明度 0.6
49 湖山水庫二 卡爾森指數 52
100 湖山水庫一 葉綠素a 2.7
... ... ... ...
974 南化水庫一 卡爾森指數 41
975 鏡面水庫二 葉綠素a 6.6
976 鏡面水庫二 總磷 0.039
997 鏡面水庫二 透明度 0.5
999 鏡面水庫二 卡爾森指數 59

112 rows × 3 columns

In [21]:
# 方法2
# df.query('欄位1 > 30 & 欄位2 == "A"')[['欄位1', '欄位2', '欄位3']]
# df.query('欄位1 > 30 | 欄位2 == "A"')[['欄位1', '欄位2', '欄位3']]

# same as the above
mydf1 = df_ctsi.query('itemname == "葉綠素a" | itemname == "總磷" | itemname == "透明度" | itemname == "卡爾森指數"')
mydf1
Out[21]:
sitename itemname itemvalue
25 湖山水庫二 葉綠素a 3.3
26 湖山水庫二 總磷 0.019
47 湖山水庫二 透明度 0.6
49 湖山水庫二 卡爾森指數 52
100 湖山水庫一 葉綠素a 2.7
... ... ... ...
974 南化水庫一 卡爾森指數 41
975 鏡面水庫二 葉綠素a 6.6
976 鏡面水庫二 總磷 0.039
997 鏡面水庫二 透明度 0.5
999 鏡面水庫二 卡爾森指數 59

112 rows × 3 columns

注意: 使用 pandas.pivot( ) 將長資料(Long data)轉換為寬資料(Wide data),以利後續資料分析。
In [23]:
# 長寬資料轉換
# 使用 pandas.pivot --> long data to wide data
df_ctsi = mydf1.pivot(index='sitename',
                      columns='itemname',
                      values='itemvalue')
df_ctsi.reset_index(inplace=True)
df_ctsi
Out[23]:
itemname sitename 卡爾森指數 總磷 葉綠素a 透明度
0 七美水庫 60 0.051 16.4 0.9
1 南化水庫一 41 0.009 2.0 2.1
2 南化水庫三 48 0.014 2.7 0.9
3 南化水庫二 45 0.010 2.5 1.2
4 寶二水庫一 57 0.085 8.8 1.8
5 小池水庫 59 0.037 8.8 0.5
6 德基水庫五 56 0.026 10.3 0.8
7 成功水庫 71 0.061 81.1 0.3
8 東衛水庫 72 0.078 75.7 0.3
9 湖山水庫一 49 0.022 2.7 1.2
10 湖山水庫二 52 0.019 3.3 0.6
11 澄清湖水庫一 58 0.048 3.4 0.5
12 澄清湖水庫三 52 0.027 3.9 1.0
13 澄清湖水庫二 52 0.028 4.7 1.1
14 澄清湖水庫四 63 0.048 31.7 0.7
15 牡丹水庫一 49 0.016 6.1 1.6
16 牡丹水庫三 50 0.021 4.5 1.4
17 牡丹水庫二 48 0.015 5.5 1.6
18 石門水庫六 56 0.088 2.5 1.0
19 興仁水庫 74 0.078 111 0.3
20 蘭湖水庫 77 0.086 127 0.2
21 西安水庫 45 0.016 2.7 1.9
22 金湖水庫 66 0.070 29.7 0.6
23 鏡面水庫二 59 0.039 6.6 0.5
24 鳳山水庫一 78 0.816 20.4 0.4
25 鳳山水庫三 80 0.763 36.4 0.4
26 鳳山水庫二 80 0.788 36.3 0.4
27 鳳山水庫四 81 0.659 86.7 0.5
In [24]:
df_ctsi.index
Out[24]:
RangeIndex(start=0, stop=28, step=1)
In [25]:
df_ctsi.dtypes
Out[25]:
itemname
sitename    object
卡爾森指數       object
總磷          object
葉綠素a        object
透明度         object
dtype: object
In [26]:
for col in df_ctsi.columns:
    if col not in ['itemname', 'sitename']:
        df_ctsi[col] = pd.to_numeric(df_ctsi[col], errors='coerce')
df_ctsi.dtypes
Out[26]:
itemname
sitename     object
卡爾森指數         int64
總磷          float64
葉綠素a        float64
透明度         float64
dtype: object
In [27]:
df_ctsi.shape # 28*5
Out[27]:
(28, 5)
In [28]:
fig = px.scatter(df_ctsi, x='卡爾森指數', y='總磷')
fig.update_layout(title_text='班級-168-李明昌', title_x=0.5)
In [29]:
# 資料摘要
# aqi 最小值為 16.00, 最大值為 123.00, 平均值為 45.58, 中位數為 34.50
pd.set_option('display.precision', 2)
df_ctsi.describe(include='all')
Out[29]:
itemname sitename 卡爾森指數 總磷 葉綠素a 透明度
count 28 28.00 2.80e+01 28.00 28.00
unique 28 NaN NaN NaN NaN
top 七美水庫 NaN NaN NaN NaN
freq 1 NaN NaN NaN NaN
mean NaN 59.93 1.43e-01 26.19 0.88
std NaN 12.23 2.57e-01 35.89 0.54
min NaN 41.00 9.00e-03 2.00 0.20
25% NaN 49.75 2.05e-02 3.38 0.47
50% NaN 57.50 4.35e-02 7.70 0.75
75% NaN 71.25 7.98e-02 32.85 1.20
max NaN 81.00 8.16e-01 127.00 2.10

2.3 探索性資料分析(Exploratory Data Analysis, EDA)¶

In [31]:
# 資料列數與行數 (28, 5)
df_ctsi.shape
Out[31]:
(28, 5)
In [32]:
# isnull 顯示資料沒有遺漏值 (Missing Values)
df_ctsi.isnull().sum()
Out[32]:
itemname
sitename    0
卡爾森指數       0
總磷          0
葉綠素a        0
透明度         0
dtype: int64
In [33]:
# 資料型態: 卡爾森指數等測量值已經正確轉換為 float64.
df_ctsi.dtypes
Out[33]:
itemname
sitename     object
卡爾森指數         int64
總磷          float64
葉綠素a        float64
透明度         float64
dtype: object
In [34]:
# 顯示前5筆
df_ctsi.head()
Out[34]:
itemname sitename 卡爾森指數 總磷 葉綠素a 透明度
0 七美水庫 60 5.10e-02 16.4 0.9
1 南化水庫一 41 9.00e-03 2.0 2.1
2 南化水庫三 48 1.40e-02 2.7 0.9
3 南化水庫二 45 1.00e-02 2.5 1.2
4 寶二水庫一 57 8.50e-02 8.8 1.8
In [35]:
# 顯示後5筆
df_ctsi.tail()
Out[35]:
itemname sitename 卡爾森指數 總磷 葉綠素a 透明度
23 鏡面水庫二 59 0.04 6.6 0.5
24 鳳山水庫一 78 0.82 20.4 0.4
25 鳳山水庫三 80 0.76 36.4 0.4
26 鳳山水庫二 80 0.79 36.3 0.4
27 鳳山水庫四 81 0.66 86.7 0.5
In [36]:
# 將卡爾森指數資料集(df_ctsi)與經緯度(df_location)資料集合併
df_ctsi = df_ctsi.merge(df_location, on = 'sitename')
df_ctsi
Out[36]:
sitename 卡爾森指數 總磷 葉綠素a 透明度 twd97lon twd97lat
0 七美水庫 60 5.10e-02 16.4 0.9 119.43 23.21
1 南化水庫一 41 9.00e-03 2.0 2.1 120.54 23.09
2 南化水庫三 48 1.40e-02 2.7 0.9 120.56 23.13
3 南化水庫二 45 1.00e-02 2.5 1.2 120.55 23.11
4 寶二水庫一 57 8.50e-02 8.8 1.8 121.04 24.72
5 小池水庫 59 3.70e-02 8.8 0.5 119.51 23.61
6 德基水庫五 56 2.60e-02 10.3 0.8 121.25 24.27
7 成功水庫 71 6.10e-02 81.1 0.3 119.63 23.58
8 東衛水庫 72 7.80e-02 75.7 0.3 119.60 23.57
9 湖山水庫一 49 2.20e-02 2.7 1.2 120.63 23.68
10 湖山水庫二 52 1.90e-02 3.3 0.6 120.63 23.68
11 澄清湖水庫一 58 4.80e-02 3.4 0.5 120.35 22.65
12 澄清湖水庫三 52 2.70e-02 3.9 1.0 120.35 22.66
13 澄清湖水庫二 52 2.80e-02 4.7 1.1 120.35 22.66
14 澄清湖水庫四 63 4.80e-02 31.7 0.7 120.35 22.66
15 牡丹水庫一 49 1.60e-02 6.1 1.6 120.78 22.13
16 牡丹水庫三 50 2.10e-02 4.5 1.4 120.78 22.15
17 牡丹水庫二 48 1.50e-02 5.5 1.6 120.78 22.14
18 石門水庫六 56 8.80e-02 2.5 1.0 121.30 24.81
19 興仁水庫 74 7.80e-02 111.0 0.3 119.61 23.55
20 蘭湖水庫 77 8.60e-02 127.0 0.2 118.38 24.45
21 西安水庫 45 1.60e-02 2.7 1.9 119.50 23.36
22 金湖水庫 66 7.00e-02 29.7 0.6 118.46 24.43
23 鏡面水庫二 59 3.90e-02 6.6 0.5 120.49 23.06
24 鳳山水庫一 78 8.16e-01 20.4 0.4 120.39 22.54
25 鳳山水庫三 80 7.63e-01 36.4 0.4 120.39 22.54
26 鳳山水庫二 80 7.88e-01 36.3 0.4 120.39 22.54
27 鳳山水庫四 81 6.59e-01 86.7 0.5 120.39 22.54

水庫CTSI卡爾森指數-資料視覺化¶

In [38]:
# 設定地理中心位置的啟始檢視位置
m = folium.Map(location=[23.97565, 120.9738819], zoom_start=8)

for index, row in df_ctsi.iterrows():

    # 將資料點使用圓形標記加在地圖上
    folium.CircleMarker(
        radius=10,                                     # 半徑
        location=[row['twd97lat'], row['twd97lon']],   # 位置
        stroke=False,                                  # 是否顯示框線
        fill=True,                                     # 是否填滿        
        fill_opacity=0.9,                              # 設定透明度: 1=完全不透明, 0.1=完全透明
        popup  ="測站: {} \n CTSI卡爾森指數: {}".format(row["sitename"], row["卡爾森指數"]),
        tooltip="測站: {} \n CTSI卡爾森指數: {}".format(row["sitename"], row["卡爾森指數"]),
    ).add_to(m)

# icon list: https://fontawesome.com/icons

# 加入置中標題
titles = '水庫卡爾森指數系統-2025.06.17-@RWPEA'
title_html = '''
             <h3 align="center" style="font-size:16px"><b>{}</b></h3>
             '''.format(titles)   
m.get_root().html.add_child(folium.Element(title_html))
Out[38]:
<branca.element.Element at 0x184a18da3f0>
In [39]:
# 繪製地理資料視覺化
m
Out[39]:
Make this Notebook Trusted to load map: File -> Trust Notebook
In [69]:
# end
In [ ]: